package XMLTranslator;

import XMLForms.TTRM;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;



public class XMLWriter {

	// Attributes read in from the TTRM object ready for writing to
	// different XML structures
	private String journalFile = "JournalFile.xml";
	private String buySell;
	private String offererID;
	private String traderID;
	private int shareCount;
	private String stockID;
	private int offerTime;
	private long traderTimeSentStamp;

	// Constructor. Takes a TTRM object and reads in the values.
	public XMLWriter(TTRM ttrm) {
		buySell = ttrm.getBuySell();
		offererID = ttrm.getOffererID();
		traderID = ttrm.getTraderID();
		shareCount = ttrm.getShareCount();
		stockID = ttrm.getStockID();
		offerTime = ttrm.getOfferTime();
		traderTimeSentStamp = ttrm.getTraderTimeSentStamp();
	}

	// Opens the JournalFile.xml file and reads the DOM
	// structure into a variable. Returns Document, which is the entire DOM
	// tree.
	public Document openFile() {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		InputStream is = null;
		DocumentBuilder docBuilder = null;
		Document doc = null;
		try {
			docBuilder = docFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			System.err.println("Error creating DocumentBuilder.");
			e.printStackTrace();
		}
		URL url = this.getClass().getClassLoader().getResource(journalFile);
		try {
			is = url.openStream();
			// Read in DOM tree from xml to doc
			doc = docBuilder.parse(is);
			is.close();
		} catch (IOException e) {
			System.err.println("I/O Error with " + url);
			e.printStackTrace();
		} catch (SAXException e) {
			System.err.println("SAX Error reading xml file " + url);
			e.printStackTrace();
		}
		return doc;

	}

	// Writes the DOM tree to the JournalFile.xml.
	public void writeToJournal(Document doc) {
		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		Transformer transformer;
		try {
			transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);

			File dir = new File(System.getProperty("user.dir"));
			StreamResult result = new StreamResult(new File(dir + "\\log\\"
					+ journalFile));
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.transform(source, result);
		} catch (TransformerConfigurationException e) {
			System.err.println("Transformer Configuration Error.");
			e.printStackTrace();
		} catch (TransformerException e) {
			System.err.println("Transformer Exception Error.");
			e.printStackTrace();
		}

	}
	
	// Takes the open Document DOM tree and adds a TTRM structure under the 
	// supplied element.
	public void writeTTRMStructure(Document doc, Element subnode){
		
		Element ttrmMessage = doc.createElement("ttrm");
		subnode.appendChild(ttrmMessage);
		
		Element buySellField = doc.createElement("BuySell");
		ttrmMessage.appendChild(buySellField);
		buySellField.appendChild(doc.createTextNode(buySell));

		Element offererIDField = doc.createElement("OffererID");
		ttrmMessage.appendChild(offererIDField);
		offererIDField.appendChild(doc.createTextNode(offererID));

		Element traderIDField = doc.createElement("TraderID");
		ttrmMessage.appendChild(traderIDField);
		traderIDField.appendChild(doc.createTextNode(traderID));

		Element shareCountField = doc.createElement("ShareCount");
		ttrmMessage.appendChild(shareCountField);
		shareCountField.appendChild(doc.createTextNode(String
				.valueOf(shareCount)));

		Element stockIDField = doc.createElement("StockID");
		ttrmMessage.appendChild(stockIDField);
		stockIDField.appendChild(doc.createTextNode(stockID));

		Element offerTimeField = doc.createElement("OfferTime");
		ttrmMessage.appendChild(offerTimeField);
		offerTimeField
				.appendChild(doc.createTextNode(String.valueOf(offerTime)));

		Element traderTimeSentStampField = doc
				.createElement("TraderTimeSentStamp");
		ttrmMessage.appendChild(traderTimeSentStampField);
		traderTimeSentStampField.appendChild(doc.createTextNode(String
				.valueOf(traderTimeSentStamp)));
	}

	// Appends JournalFile.xml with the TTRM formatted message.
	public void composeTTRM() {

		Document doc = openFile();
		Element rootElement = doc.getDocumentElement();
		
		writeTTRMStructure(doc, rootElement);

		writeToJournal(doc);
		System.out.println("TTRM appended to Journal File.");
	}

	// Appends JournalFile.xml with the TVFM formatted message.
	public void composeTVFM(String failureID, String message) {

		String failureField = failureID;
		String failureMessage = message;

		Document doc = openFile();

		Element rootElement = doc.getDocumentElement();

		Element tvfmMessage = doc.createElement("tvfm");
		rootElement.appendChild(tvfmMessage);

		writeTTRMStructure(doc, tvfmMessage);
		
		//Additional fields for the TVFM Structure
		Element failureFieldField = doc.createElement("FailureField");
		tvfmMessage.appendChild(failureFieldField);
		failureFieldField.appendChild(doc.createTextNode(failureField));

		Element failureMessageField = doc.createElement("FailureMessage");
		tvfmMessage.appendChild(failureMessageField);
		failureMessageField.appendChild(doc.createTextNode(failureMessage));

		writeToJournal(doc);
		System.out.println("TVFM appended to Journal File.");
	}

	// Appends JournalFile.xml with the WTRM formatted message.
	// This message has a different structure and so doesn't use writeTTRMStructure
	// method.
	public void composeWTRM(String companyID) {

		String firmID = companyID;
		String firmSequenceNumber = firmID + "-RBSFRM-" + traderTimeSentStamp;

		Document doc = openFile();

		Element rootElement = doc.getDocumentElement();

		Element wtrmMessage = doc.createElement("wtrm");
		rootElement.appendChild(wtrmMessage);

		Element firmIDField = doc.createElement("FirmID");
		wtrmMessage.appendChild(firmIDField);
		firmIDField.appendChild(doc.createTextNode(firmID));

		Element traderIDField = doc.createElement("TraderID");
		wtrmMessage.appendChild(traderIDField);
		traderIDField.appendChild(doc.createTextNode(traderID));

		Element shareCountField = doc.createElement("ShareCount");
		wtrmMessage.appendChild(shareCountField);
		shareCountField.appendChild(doc.createTextNode(String
				.valueOf(shareCount)));

		Element stockIDField = doc.createElement("StockID");
		wtrmMessage.appendChild(stockIDField);
		stockIDField.appendChild(doc.createTextNode(stockID));

		Element buySellField = doc.createElement("BuySell");
		wtrmMessage.appendChild(buySellField);
		buySellField.appendChild(doc.createTextNode(buySell));

		Element offerTimeField = doc.createElement("OfferTime");
		wtrmMessage.appendChild(offerTimeField);
		offerTimeField
				.appendChild(doc.createTextNode(String.valueOf(offerTime)));

		Element tradeRequestTimeField = doc.createElement("TradeRequestTime");
		wtrmMessage.appendChild(tradeRequestTimeField);
		tradeRequestTimeField.appendChild(doc.createTextNode(String
				.valueOf(traderTimeSentStamp)));

		Element firmSequenceNumberField = doc
				.createElement("FirmSequenceNumber");
		wtrmMessage.appendChild(firmSequenceNumberField);
		firmSequenceNumberField.appendChild(doc
				.createTextNode(firmSequenceNumber));

		writeToJournal(doc);
		System.out.println("WTRM appended to Journal File.");
	}

}
